﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using RG.Common.Export;
using RG.Common.WPF.Commands;

namespace RG.Common.WPF.Dialogs
{

    public class ColumnPresetVM
    {
        public ColumnPreset ColumnPreset { get; set; }

        public bool IsVisible
        {
            get
            {
                return ColumnPreset.Visible == Visibility.Visible ? true : false;
            }
            set
            {
                ColumnPreset.Visible = value ? Visibility.Visible : Visibility.Collapsed;
            }
        }
    }

    [SupportDataBinding]
    public class ColumnDataGridPresetDialogVM : BaseEditableObject<List<ColumnPreset>>, IEditableDialogDataErrorInfo
    {
        private bool isCheckBoxEdit = false;
        public bool IsCheckBoxEdit
        {
            get { return isCheckBoxEdit; }
            set { isCheckBoxEdit = value; }
        }

        [DependOn("IsCheckBoxEdit")]
        public bool ButtonsEnabled { get { return !IsCheckBoxEdit; } }

        // Для настройки колонок в таблицах
        private ObservableCollection<IColumnInfo> SetColumns()
        {
            var col = new ObservableCollection<IColumnInfo>
                          {
                              new ColumnInfoInt<ColumnPresetVM>("№", 25, x => x.ColumnPreset.DisplayPosition + 1),
                              new ColumnInfoBool<ColumnPresetVM>("*", 25, x => x.IsVisible)
                                  {TemplateName = "CheckBoxCellTemplate"},
                              new ColumnInfoString<ColumnPresetVM>("Заголовок", ColumnGridWidthType.Star,
                                                                   x => x.ColumnPreset.Header),
                              new ColumnInfoNum<ColumnPresetVM>("Ширина", 55, x => x.ColumnPreset.Width)
                                  {TemplateName = "WidthCellTemplate"}
                          };
            return col;
        }

        // Для выбора вариантов с их комментированием
        private ObservableCollection<IColumnInfo> SetChecks()
        {
            var col = new ObservableCollection<IColumnInfo>
                          {
                              new ColumnInfoInt<ColumnPresetVM>("№", 50, x => x.ColumnPreset.DisplayPosition + 1),
                              new ColumnInfoBool<ColumnPresetVM>("*", 25, x => x.IsVisible)
                                  {TemplateName = "CheckBoxCellTemplate"},
                              new ColumnInfoString<ColumnPresetVM>("Наименование", ColumnGridWidthType.Star,
                                                                   x => x.ColumnPreset.Header),
                              new ColumnInfoString<ColumnPresetVM>("Комментарий", ColumnGridWidthType.Star,
                                                                   x => x.ColumnPreset.Comment)
                                  {TemplateName = "CommentCellTemplate"}
                          };
            return col;
        }

        public IEnumerable<IColumnInfo> Columns { get; set; }

        public BindableCollection<ColumnPresetVM> Data { get; set; }

        public ColumnPresetVM SelectedItem { get; set; }

        // изврат, но иначе почему-то CommandParament ругаиЦа и всё громко падает при биндинге UpCmd и DownCmd
        public int MoveZero { get { return 0; } }
        public int MoveOne { get { return 1; } }
        public int MoveTwo { get { return 2; } }

        public ICommand UpCmd { get; set; }
        public ICommand DownCmd { get; set; }

        public ColumnDataGridPresetDialogVM()
        {
            UpCmd = new DelegateCommand<int>(DoUpItem, x => SelectedItem != null);
            DownCmd = new DelegateCommand<int>(DoDownItem, x => SelectedItem != null);
        }

        // двигаем вниз
        private void DoDownItem(int step)
        {
            if (SelectedItem.ColumnPreset.DisplayPosition == Item.Count - 1) return;
            if (step == 0) step = Item.Count;
            ChangeItems(SelectedItem.ColumnPreset.DisplayPosition, SelectedItem.ColumnPreset.DisplayPosition + step);
        }

        // двигаем вверх
        private void DoUpItem(int step)
        {
            if (SelectedItem.ColumnPreset.DisplayPosition == 0) return;
            if (step == 0) step = Item.Count;
            ChangeItems(SelectedItem.ColumnPreset.DisplayPosition, SelectedItem.ColumnPreset.DisplayPosition - step);
        }

        protected override void OnItemChange()
        {
            Columns = IsCheckBoxEdit ? SetChecks() : SetColumns();
            SetData(Item);
        }

        // сортируем по DisplayPosition и показываем
        public void SetData(List<ColumnPreset> preset)
        {
            var lst = new List<ColumnPresetVM>();
            foreach (var columnPreset in preset.OrderBy(x => x.DisplayPosition))
                lst.Add(new ColumnPresetVM{ColumnPreset = columnPreset});
            Data = new BindableCollection<ColumnPresetVM>(lst);
        }

        // метод для обмена двух элементов на позициях form и to 
        public void ChangeItems(int from, int to)
        {
            if (from >= Item.Count || from == to || from < 0) return;
            if (to >= Item.Count) to = Item.Count - 1;
            if (to < 0) to = 0;
            var fromItem = Item.FirstOrDefault(x => x.DisplayPosition == from);
            if (from > to) // двигаем вверх, меняем позиции всех элементов, что выше
                foreach (var itm in Item.Where(x => x.DisplayPosition < from && x.DisplayPosition >= to))
                    itm.DisplayPosition++;
            if (from < to) // двигаем вниз, меняем позиции всех элементов, что ниже
                foreach (var itm in Item.Where(x => x.DisplayPosition > from && x.DisplayPosition <= to))
                    itm.DisplayPosition--;
            // ставим текущий элемент на новое место
            fromItem.DisplayPosition = to;
            SetData(Item);
            SelectedItem = Data.FirstOrDefault(x => x.ColumnPreset.DisplayPosition == to);
        }

        public string LastError()
        {
            return "";
        }
    }
}
